using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UniversalAdmin.Application.Dto;
using UniversalAdmin.Application.Commands;
using System.Linq;
using UniversalAdmin.Infrastructure.Data.Contexts;
using UniversalAdmin.Shared.Enums;
using UniversalAdmin.Domain.Entities.App;

namespace UniversalAdmin.Application.Services
{
    public class AppOperationLogService : IAppOperationLogService
    {
        private readonly AdminDbContext _db;
        public AppOperationLogService(AdminDbContext db)
        {
            _db = db;
        }

        public async Task<ApiResult<PagedResult<OperationLogDto>>> GetPagedAsync(PagedQuery query)
        {
            var q = from log in _db.AppOperationLogs
                    join user in _db.AppUsers on log.UserId equals user.Id into userJoin
                    from user in userJoin.DefaultIfEmpty()
                    select new { log, user };
            
            if (!string.IsNullOrWhiteSpace(query.Search))
            {
                q = q.Where(x => x.log.Operation.Contains(query.Search) || 
                                 x.log.Message.Contains(query.Search) ||
                                 x.log.Module.Contains(query.Search) ||
                                 (x.user != null && x.user.Username.Contains(query.Search)));
            }
            
            // 支持按日志级别筛选
            if (!string.IsNullOrWhiteSpace(query.Level))
            {
                q = q.Where(x => x.log.LogLevel == query.Level);
            }
            
            // 支持按模块筛选
            if (!string.IsNullOrWhiteSpace(query.Module))
            {
                q = q.Where(x => x.log.Module.Contains(query.Module));
            }
            
            // 支持按时间范围筛选
            if (!string.IsNullOrWhiteSpace(query.StartTime) && DateTime.TryParse(query.StartTime, out var startTime))
            {
                q = q.Where(x => x.log.CreatedAt >= startTime);
            }
            
            if (!string.IsNullOrWhiteSpace(query.EndTime) && DateTime.TryParse(query.EndTime, out var endTime))
            {
                q = q.Where(x => x.log.CreatedAt <= endTime);
            }
            
            var total = await Task.FromResult(q.Count());
            var items = q.OrderByDescending(x => x.log.CreatedAt)
                .ThenBy(x => x.log.Id)
                .Skip((query.Page - 1) * query.Size)
                .Take(query.Size)
                .Select(x => new OperationLogDto
                {
                    Id = x.log.Id,
                    Operation = x.log.Operation,
                    Description = x.log.Action,
                    UserId = x.log.UserId,
                    Username = x.user != null ? x.user.Username : string.Empty,
                    CreatedAt = x.log.CreatedAt,
                    LogLevel = x.log.LogLevel,
                    Module = x.log.Module,
                    Message = x.log.Message,
                    Details = x.log.Details,
                    Exception = x.log.Exception,
                    RequestBody = x.log.RequestBody,
                    ResponseBody = x.log.ResponseBody,
                    StatusCode = x.log.StatusCode,
                    ExecutionTime = x.log.ExecutionTime,
                    IpAddress = x.log.IpAddress,
                    UserAgent = x.log.UserAgent
                })
                .ToList();
            
            return ApiResult<PagedResult<OperationLogDto>>.Success(200, "操作成功", new PagedResult<OperationLogDto>(items, total, query.Page, query.Size));
        }

        public async Task<ApiResult<IEnumerable<OperationLogDto>>> GetAllAsync(string? search = null)
        {
            var q = from log in _db.AppOperationLogs
                    join user in _db.AppUsers on log.UserId equals user.Id into userJoin
                    from user in userJoin.DefaultIfEmpty()
                    select new { log, user };
            
            if (!string.IsNullOrWhiteSpace(search))
            {
                q = q.Where(x => x.log.Operation.Contains(search) || 
                                 x.log.Message.Contains(search) ||
                                 x.log.Module.Contains(search) ||
                                 (x.user != null && x.user.Username.Contains(search)));
            }
            
            var items = q.OrderByDescending(x => x.log.CreatedAt)
                .Select(x => new OperationLogDto
                {
                    Id = x.log.Id,
                    Operation = x.log.Operation,
                    Description = x.log.Action,
                    UserId = x.log.UserId,
                    Username = x.user != null ? x.user.Username : string.Empty,
                    CreatedAt = x.log.CreatedAt,
                    LogLevel = x.log.LogLevel,
                    Module = x.log.Module,
                    Message = x.log.Message,
                    Details = x.log.Details,
                    Exception = x.log.Exception,
                    RequestBody = x.log.RequestBody,
                    ResponseBody = x.log.ResponseBody,
                    StatusCode = x.log.StatusCode,
                    ExecutionTime = x.log.ExecutionTime,
                    IpAddress = x.log.IpAddress,
                    UserAgent = x.log.UserAgent
                })
                .ToList();
            
            return ApiResult<IEnumerable<OperationLogDto>>.Success(200, "操作成功", items);
        }

        public async Task<ApiResult<OperationLogDto>> GetByIdAsync(Guid id)
        {
            var log = await _db.AppOperationLogs.FindAsync(id);
            if (log == null)
                return ApiResult<OperationLogDto>.Failed((int)ApiStatusCode.NOT_FOUND, "日志不存在");

            var user = await _db.AppUsers.FindAsync(log.UserId);
            
            var dto = new OperationLogDto
            {
                Id = log.Id,
                Operation = log.Operation,
                Description = log.Action,
                UserId = log.UserId,
                Username = user?.Username ?? string.Empty,
                CreatedAt = log.CreatedAt,
                LogLevel = log.LogLevel,
                Module = log.Module,
                Message = log.Message,
                Details = log.Details,
                Exception = log.Exception,
                RequestBody = log.RequestBody,
                ResponseBody = log.ResponseBody,
                StatusCode = log.StatusCode,
                ExecutionTime = log.ExecutionTime,
                IpAddress = log.IpAddress,
                UserAgent = log.UserAgent
            };
            
            return ApiResult<OperationLogDto>.Success(200, "获取成功", dto);
        }
    }
} 